<template>
    <div class="exp-editor">
        <div class="editor-fields" v-if="false">
            <h4>条件字段</h4>
            <Button v-for="(field,index) in fields" type="ghost" :key="index" @click="addFieldExp(field.code)">
                {{field.code}}
            </Button>
            <div class="clear"></div>
        </div>
        <Row class="editor-body">
            <Col v-if="hasFunc" :span="4">
            <Button v-for="fun in functional" type="ghost" :key="fun.code" @click="addFuncExp(fun.code)">
                {{fun.code}}
            </Button>
            </Col>
            <Col class="editor-content" :span="hasFunc?20:24">
            <div v-show="expression && expression.length || !placeholderShow" ref="input" class="exp-input ivu-input" user-modify="read-write-plaintext-only" @mouseup="saveRange" @change="saveRange" contenteditable="true" v-focus="inputFocus" @input="codeInput" v-html="expression">
            </div>
            <div v-show="!(expression && expression.length || !placeholderShow)" class="editor-placeholder ivu-input" @click="palceholderClick">
                {{placeholder}}
            </div>
            </Col>
        </Row>
    </div>
</template>
<script>
export default {
    props: {
        hasFunc: {
            default: false
        },
        placeholder: {
            default: '请输入条件表达式'
        },
        value: {}
    },
    data() {
        return {
            expression: this.value,
            inputFocus: null,
            placeholderShow: true,
            functional: [{
                code: 'FUNC1'
            }, {
                code: 'FUNC2'
            }],
            fields: [{
                code: 'name'
            }, {
                code: 'number'
            }]
        }
    },
    watch: {
        value(v) {
            //this.expression = v
        }
    },
    methods: {
        codeInput(e) {
            this.$emit('input', this.formatExp())
        },
        formatExp() {
            return this.$refs.input.innerHTML
        },
        addFieldExp(code) {
            this.expression = this.insertExp(this.fieldHtml(code))
            this.inputFocus = true
        },
        addFuncExp(code) {
            this.expression = this.insertExp(this.funcHtml(code))
            this.inputFocus = true
        },
        saveRange() {
            var selection = window.getSelection ? window.getSelection() : document.selection;
            var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0);
            this.range = range;
        },
        //编辑器光标移动到最后
        pointLast() {
            var input = this.$refs.input
            if (window.getSelection) {
                //ie11 10 9 ff safari
                input.focus() //解决ff不获取焦点无法定位问题
                let range = window.getSelection();//创建range
                range.selectAllChildren(input);//range 选择obj下所有子内容
                range.collapseToEnd();//光标移至最后
            } else if (document.selection) {
                //ie10 9 8 7 6 5
                let range = document.selection.createRange();//创建选择对象
                range.moveToElementText(input);//range定位到obj
                range.collapse(false);//光标移至最后
                range.select();
            }
        },
        palceholderClick() {
            this.placeholderShow = false
            this.$nextTick(() => {
                this.$refs.input.focus()
            })
        },
        insertExp(str) {
            var selection = document.selection || window.getSelection()
            var input = this.$refs.input
            input.focus()
            //未选择的情况直接将对象加到末尾
            if (!this.range) {
                input.innerHTML += str
                this.pointLast()
            } else {
                if (document.selection) {
                    var range = selection.createRange ? selection.createRange() : selection.getRangeAt(0);
                    range.pasteHTML(str)
                    range.collapse(false)
                    range.select();
                } else {
                    selection.addRange(this.range)
                    range = this.range
                    range.collapse(false)
                    var hasR = range.createContextualFragment(str)
                    var hasR_lastChild = hasR.lastChild
                    while (hasR_lastChild && hasR_lastChild.nodeName.toLowerCase() === 'br' && hasR_lastChild.previousSibling && hasR_lastChild.previousSibling.nodeName.toLowerCase() === 'br') {
                        var e = hasR_lastChild;
                        hasR_lastChild = hasR_lastChild.previousSibling;
                        hasR.removeChild(e)
                    }
                    range.insertNode(hasR);
                    if (hasR_lastChild) {
                        range.setEndAfter(hasR_lastChild);
                        range.setStartAfter(hasR_lastChild)
                    }
                    selection.removeAllRanges();
                    selection.addRange(range)
                }
            }
            return input.innerHTML
        },
        funcHtml(code) {
            return ` <span class="exp-func" contenteditable="false">${code}(<span class="exp-param" contenteditable="true"></span>)</span> `
        },
        fieldHtml(code) {
            return ` <input class="exp-field" disabled value="${code}"/> `
        }
    },
    created() {
        if (this.value) {
            this.expression = this.value
        }
    },
    mounted() {
    }
}
</script>
<style lang="less">
.exp-editor {
    display: flex;
    flex-direction: column;
    height: 100%;
    .editor-body {
        display: flex;
        flex-direction: row;
        flex: 1;
    }
    .editor-placeholder {
        padding: 15px;
        height: 100%;
        color: #dddddd
    }
    .editor-fields {
        padding: 15px 10px;
        background: #f9f9f9;
        button.ivu-btn {
            color: #495060;
            background-color: transparent;
            border-color: #dddee1;
            background: #fff;
            padding: 4px 12px;
            margin: 0 4px;
        }
    }
    .editor-content {
        /*height: 100%;*/
    }
    .exp-input {
        padding: 15px;
        min-height: 100%;
        height: auto;
        width: 100%;
        font-size: 14px;
        &:focus {
            outline: none;
        }
    }
    .exp-param {
        background: #fff;
        color: #555;
        min-width: 16px;
        padding-left: 8px;
        padding-right: 8px;
        &:focus {
            outline: none;
        }
    }
    .exp-func {
        display: inline-block;
        padding: 2px 6px;
        margin: 0 2px;
        background: transparent;
        color: #17d65d;
        font-weight: bold;
    }
    .exp-span {}
    .exp-field {
        display: inline-block;
        padding: 2px 6px;
        margin: 0 2px;
        background: #00BCD4;
        border-radius: 4px;
        color: #fff;
        caret-color: #000;
    }
}
</style>